package Ejercicio5;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicLong;


public class ServidorChat implements Servidor {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	private CopyOnWriteArrayList<Cliente> clientes;
	private AtomicLong numMensaje; 
	Executor pool;
	
	
	public ServidorChat() {
		clientes = new CopyOnWriteArrayList<Cliente>();
		numMensaje = new AtomicLong();
		pool = Executors.newFixedThreadPool(20);
	}
	@Override
	public void difundir(final String mensaje) throws RemoteException {
		final long n = numMensaje.getAndIncrement();
		for (final Cliente c : clientes) {
			pool.execute(new Runnable() {
				
				@Override
				public void run() {
					try {
						c.recibir(n + ": " + mensaje);
					} catch (RemoteException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
				}
			});
		}
	}
	
	private int contador = 1;
	@Override
	public int inscribirse(Cliente c) throws RemoteException {
		clientes.add(c);
		return contador++;
	}
	
	
	public static void main(String[] main) {
        try {
        	ServidorChat obj = new ServidorChat();
        	Servidor stub = (Servidor) UnicastRemoteObject.exportObject(obj, 0);
        	
        	ClienteLog clienteLog = new ClienteLog();
        	obj.inscribirse(clienteLog);
        	// Bind the remote object's stub in the registry
            Registry registry = LocateRegistry.getRegistry();

        	Thread chat = new Thread(clienteLog);
        	chat.start();
        	
	        registry.rebind("Servidor", stub);

            System.err.println("Server ready");
        } catch (Exception e) {
            System.err.println("Server exception: " + e.toString());
            e.printStackTrace();
        }
	}

}
